package org.jeecg.zhenxuan.Controller;

import com.alibaba.fastjson.JSONObject;
import org.jeecg.zhenxuan.CommonUtils.CommonUtils;
import org.jeecg.zhenxuan.CommonUtils.SignatureUtil;
import org.jeecg.zhenxuan.Entity.PointFlow;
import org.jeecg.zhenxuan.Entity.UsersPoint;
import org.jeecg.zhenxuan.Model.PointBasicModel;
import org.jeecg.zhenxuan.Repository.PointFlowRepository;
import org.jeecg.zhenxuan.Repository.UserAddRepository;
import org.jeecg.zhenxuan.Repository.UserPointTempRepository;
import org.jeecg.zhenxuan.Repository.UserRepository;
import org.jeecg.zhenxuan.Service.PointFlowAddService;
import org.jeecg.zhenxuan.Service.UserAddService;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
import javax.validation.Valid;
import java.util.Date;
import java.util.Random;

@Slf4j
@RestController
public class PointTradingStdController {

    @Autowired
    private UserAddService userService;

    @Autowired
    private PointFlowAddService pointFlowService;


    /**
     * add by 2019年12月13日 星期五
     */
    @Autowired
    private PointFlowRepository pointFlowRepository;

    @Autowired
    UserRepository userRepository;

    @Autowired
    private UserAddRepository userAddRepository;



    @Value(value = "${ppp-swagger.addpoint-randombound}")
    private Integer addPointRandomBound;


    /**
     * 生成 1 - x （包括1、x）随机数
     * @param x
     * @return
     */

    public static int randomWithNotZero(int x) {
        int y = 0;
        Random random = new Random();
        y = random.nextInt(x + 1);
        if (y == 0) {
            return randomWithNotZero(x + 1);
        } else {
            return y;
        }
    }

    @RequestMapping("/testProc001")
    public String testproc(HttpServletRequest request){
        System.out.println(addPointRandomBound);

        return "" + addPointRandomBound + "   :  " + randomWithNotZero(addPointRandomBound);
    }

    /**
     * add by 2019年12月13日 星期五
     * 减豆子
     * @param userNo
     * @param boNo
     * @param point
     * @param ts
     * @param appId
     * @param channel
     * @param phoneNumber
     * @param param01
     * @param param02
     * @param sign
     * @return
     */
    @ResponseBody
    @RequestMapping("/reducePointStd")
    @Transactional
    public JSONObject reducePointByOpenIdStd(@RequestParam(required = true) String userNo, String boNo, @Valid PointBasicModel pointBasicModel , @RequestParam(required = true) String ts, String appId, @RequestParam(defaultValue = "default") String channel, String phoneNumber , String param01, String param02, String sign
                                                , HttpServletRequest request){
        JSONObject result = new JSONObject();

        log.info("userNo"+userNo+" , "+channel+" , "+pointBasicModel.getCount());

        Integer point = pointBasicModel.getCount();
        //非空判断
        if (StringUtils.isBlank(userNo) || StringUtils.isBlank(ts) || StringUtils.isBlank(sign) ||  StringUtils.isBlank(boNo) || point==null) {
            result.put("status", 1);
            result.put("message", "参数为空！");
            return result;
        }
        //生成签名
        JSONObject json = new JSONObject();
        json.put("userNo",userNo);
        json.put("boNo",boNo);
        json.put("point",point);
        json.put("ts",ts);
        //md5key
        String md5Key = "xuanzhen";
        String mySign = SignatureUtil.makeSignature(json,md5Key);
        System.out.println(mySign);
        //检验签名
        if(!mySign.equals(sign)){
            result.put("status", 1);
            result.put("message", "签名错误");
            return result;
        }
        try {
            if(point < 0|| point>=2147483647) {
                result.put("status", 1);
                result.put("message", "商品数据出现错误，请稍后再试");
                return result;
            }
            PointFlow pointFlowTemp = new PointFlow();
            pointFlowTemp.setOpenId(userNo);
            pointFlowTemp.setOperation("reduce");
            pointFlowTemp.setOperationTime(new Date());
            pointFlowTemp.setCount(point);
//            add by 2020年4月3日 星期五
//            增加业务流水号
            pointFlowTemp.setParam02(boNo);

            pointFlowTemp.setChannel(channel);
            pointFlowTemp.setTransactionSequences(ts);
            pointFlowTemp.setStatus(1);

            pointFlowRepository.save(pointFlowTemp);
//            UsersPoint usersPoint = userRepository.getUserTestByOpenId(userNo);
            UsersPoint usersPoint = userRepository.findUsersPointByOpenIdAndChannel(userNo , channel);
            if(usersPoint==null){
                result.put("status", 1);
                result.put("message", "查询数据失败");
                return result;
            }
            if((usersPoint.getPointTotal()-point)<0){
                result.put("status", 1);
                result.put("message", "豆子数量不够");
                return result;
            }
            System.out.println(usersPoint.getPointTotal()-point);
//            int Total = userRepository.updatePointTotal(usersPoint.getPointTotal()-point,userNo);
            int Total = userAddRepository.updatePointStdReduce(usersPoint.getPointTotal()-point,userNo , channel , new Date());

            System.out.println(Total);
            if(Total==0){
                result.put("status", 1);
                result.put("message", "扣减豆子失败");
            }
            usersPoint.setPointTotal(usersPoint.getPointTotal()-point);
            usersPoint.setLastModifyTime(new Date());

//            userRepository.save(usersPoint);
            result.put("point",usersPoint.getPointTotal());
            result.put("status",0);
            result.put("message","豆子已经减掉了");
            result.put("sn", "" + CommonUtils.randomSixDigital());
            return result;

        }catch (Exception e){
            log.error(e.getLocalizedMessage());
            e.printStackTrace();
            //事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            result.put("status", 2);
            result.put("message", "没有查到数据"+e.getLocalizedMessage());
        }
        return result;
    }


    /**
     * test
     */
    /**
     * add by 2019年12月13日 星期五
     * 减豆子
     * @param userNo
     * @param boNo
     * @param point
     * @param ts
     * @param appId
     * @param channel
     * @param phoneNumber
     * @param param01
     * @param param02
     * @param sign
     * @return
     */
    @ResponseBody
    @RequestMapping("/reducePointStdTest")
    @Transactional
    public JSONObject reducePointByOpenIdStdTest(String userNo, String boNo, Integer point, String ts, String appId, String channel, String phoneNumber , String param01, String param02, String sign){
        JSONObject result = new JSONObject();

        //非空判断
        if (StringUtils.isBlank(userNo) || StringUtils.isBlank(ts) || StringUtils.isBlank(sign) ||  StringUtils.isBlank(boNo) || point==null) {
            result.put("status", 1);
            result.put("message", "参数为空！");
            return result;
        }
        //生成签名
        JSONObject json = new JSONObject();
        json.put("userNo",userNo);
        json.put("boNo",boNo);
        json.put("point",point);
        json.put("ts",ts);
        //md5key
        String md5Key = "xuanzhen";
        String mySign = SignatureUtil.makeSignature(json,md5Key);
        System.out.println(mySign);
        //检验签名
/*        if(!mySign.equals(sign)){
            result.put("status", 1);
            result.put("message", "签名错误");
            return result;
        }*/
        try {
            if(point < 0|| point>=2147483647) {
                result.put("status", 1);
                result.put("message", "商品数据出现错误，请稍后再试");
                return result;
            }
            PointFlow pointFlowTemp = new PointFlow();
            pointFlowTemp.setOpenId(userNo);
            pointFlowTemp.setOperation("reduce");
            pointFlowTemp.setOperationTime(new Date());
            pointFlowTemp.setCount(point);

            pointFlowTemp.setChannel(channel);
            pointFlowTemp.setTransactionSequences(ts);
            pointFlowTemp.setStatus(1);

            pointFlowRepository.save(pointFlowTemp);
            UsersPoint usersPoint = userRepository.getUserTestByOpenId(userNo);
            if(usersPoint==null){
                result.put("status", 1);
                result.put("message", "查询数据失败");
                return result;
            }
            if((usersPoint.getPointTotal()-point)<0){
                result.put("status", 1);
                result.put("message", "豆子数量不够");
                return result;
            }
            System.out.println(usersPoint.getPointTotal()-point);
            int Total = userRepository.updatePointTotal(usersPoint.getPointTotal()-point,userNo);
            System.out.println(Total);
            if(Total==0){
                result.put("status", 1);
                result.put("message", "扣减豆子失败");
            }
            usersPoint.setPointTotal(usersPoint.getPointTotal()-point);
            usersPoint.setLastModifyTime(new Date());

            userRepository.save(usersPoint);
            result.put("point",usersPoint.getPointTotal());
            result.put("status",0);
            result.put("message","豆子已经减掉了");
            result.put("sn", "" + CommonUtils.randomSixDigital());
            return result;

        }catch (Exception e){
            log.error(e.getLocalizedMessage());
            e.printStackTrace();
            //事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            result.put("status", 2);
            result.put("message", "没有查到数据");
        }
        return result;
    }



    /**
     * 2019年12月13日 星期五
     * 添加豆子
     * @param userNo
     * @param count
     * @return
     */
    @ResponseBody
    @RequestMapping("/addPointStd")
    @org.springframework.transaction.annotation.Transactional
    public JSONObject addPointByOpenId(@RequestParam(required = true) String userNo, @RequestParam(required = true) String boNo, String name , @Valid PointBasicModel pointBasicModel, String appId,
                                       @RequestParam(defaultValue = "default")String channel, String phoneNumber , String param01, String param02, @RequestParam(required = true) String ts, @RequestParam(required = true) String sign , BindingResult result2 , HttpServletRequest request) {
        JSONObject result = new JSONObject();

        Integer count = pointBasicModel.getCount();

        log.debug(result2.toString());

        /**
         * 2019年12月24日 星期二
         */
        param01 = ""+randomWithNotZero(addPointRandomBound);

        //非空判断
        if (StringUtils.isBlank(userNo) || count == null || StringUtils.isBlank(ts) || StringUtils.isBlank(sign) || StringUtils.isBlank(boNo) ) {
            result.put("status", 1);
            result.put("message", "参数为空！");
            return result;
        }

        try{
            //数字判断,并判断取值范围
            if(count < 0){
                result.put("status", 1);
                result.put("message", "豆子数量格式不能是负数");
                return result;
            }
        }catch (Exception e){
            result.put("status", 1);
            result.put("message", "豆子数量格式不正确");
            return result;
        }

        //生成签名
        JSONObject json = new JSONObject();
        json.put("userNo",userNo);
        json.put("boNo",boNo);
        json.put("totalPoint",count);
        json.put("ts",ts);
        //md5key
        String md5Key = "xuanzhen";
        String mySign = SignatureUtil.makeSignature(json,md5Key);

        //检验签名
        if(!mySign.equals(sign)){
            result.put("status", 1);
            result.put("message", "签名错误");
            return result;
        }

        try {
            //操作user表豆子总数，添加豆子

/*            if (org.springframework.util.StringUtils.isEmpty(channel)) {
                channel = "default";
            }*/

            UsersPoint user = userService.updateUserStd(userNo, count,"add" , appId,channel,phoneNumber ,name);

            //添加失败，返回为null，事务回滚，返回响应
            if(user == null){
                //事务回滚
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                //响应
                result.put("status", 1);
                result.put("message", "未查询到用户数据");
                return result;
            }
//          modify by 2020年4月3日 星期五
//           增加 绑定业务流水号

            PointFlow pointFlowTemp = new PointFlow(null,userNo,"add",new Date(),count,channel,1,ts,param01,boNo );
            PointFlow pointFlow = pointFlowRepository.save(pointFlowTemp);

            //响应信息
            result.put("status", 0);
            result.put("message", "添加成功");
            result.put("point",user.getPointTotal());
            result.put("sn",pointFlow.getId());
            result.put("BagNo",param01);
        } catch (Exception e) {
            //发生异常
            //事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            result.put("status",2);
            result.put("message", "操作失败");
        }
        return result;
    }


    /**
     * 分页查询豆子流水明细
     * add by 2019年12月16日 星期一
     * @param userNo openid
     * @param pageIndex 当前页码
     * @param elementCount 每页显示的数量
     * @return
     */
    @RequestMapping("/listPointFlowDetailStd")
    @ResponseBody
    public JSONObject listPointFlowDetail(@RequestParam(required = true)String userNo, String channel , @RequestParam(required = true)String pageIndex, @RequestParam(required = true)String elementCount, @RequestParam(required = true)String ts, String sign
                                        , HttpServletRequest request){

        JSONObject result = new JSONObject();

        //非空判断
        if(userNo == null || pageIndex == null || elementCount ==null){
            result.put("status", 1);
            result.put("message", "参数为空！");
            return result;
        }


        //生成签名
        JSONObject json = new JSONObject();
        json.put("userNo",userNo);
        json.put("pageIndex",pageIndex);
        json.put("elementCount",elementCount);
        json.put("ts",ts);
        String md5Key = "xuanzhen";
        String mySign = SignatureUtil.makeSignature(json,md5Key);


        //检验签名
        if(!mySign.equals(sign)){
            result.put("status", 1);
            result.put("message", "签名错误");
            return result;
        }

        try{

//            log.info(userNo + channel ,pageIndex , elementCount);
            //调用分页查询方法
            JSONObject jsonObject = pointFlowService.listPointFlowDetailStd(userNo,channel , pageIndex, elementCount);

            result.put("status", 0);
            result.put("message", "查询成功");
            result.put("result",jsonObject);

        }catch (Exception e){
            log.error(e.getMessage());
            result.put("status", 2);
            result.put("message", "查询失败");
        }

        return result;
    }


    /**
     * 分页查询豆子流水明细
     * add by 2019年12月16日 星期一
     * @param userNo openid
     * @param pageIndex 当前页码
     * @param elementCount 每页显示的数量
     * @return
     */
    @RequestMapping("/liststd")
    @ResponseBody
    public JSONObject listPointFlowDetailTest(String userNo, @RequestParam(defaultValue = "default") String channel , String pageIndex, String elementCount, String ts, String sign , HttpServletRequest request){

        JSONObject result = new JSONObject();

/*
        //非空判断
        if(userNo == null || pageIndex == null || elementCount ==null){
            result.put("status", 1);
            result.put("message", "参数为空！");
            return result;
        }


        //生成签名
        JSONObject json = new JSONObject();
        json.put("userNo",userNo);
        json.put("pageIndex",pageIndex);
        json.put("elementCount",elementCount);
        json.put("ts",ts);
        String md5Key = "xuanzhen";
        String mySign = SignatureUtil.makeSignature(json,md5Key);


        //检验签名
        if(!mySign.equals(sign)){
            result.put("status", 1);
            result.put("message", "签名错误");
            return result;
        }
*/

        try{

            //调用分页查询方法
            JSONObject jsonObject = pointFlowService.listPointFlowDetailStd(userNo,channel , pageIndex, elementCount);

            result.put("status", 0);
            result.put("message", "查询成功");
            result.put("result",jsonObject);

        }catch (Exception e){
            log.error(e.getLocalizedMessage()+ e.getMessage());
            result.put("status", 2);
            result.put("message", "查询失败");
        }

        return result;
    }


    /**
     * 根据用户openId查询积分数
     * modify by 2019年12月16日 星期一
     * @param openid
     * @return
     */
    @ResponseBody
    @RequestMapping("/getUserPointNumber")
    public JSONObject getUserName(@RequestParam(name = "openId" , required = true) String openid , @RequestParam(defaultValue = "default") String channel , HttpServletRequest request) {

        log.warn("############### IP "+request.getRemoteAddr());

        JSONObject result = new JSONObject();
        JSONObject jsonObject = new JSONObject();
        if (openid == null || openid.equals("")) {
            result.put("status", 1);
            result.put("message", "参数为空！");
            return result;
        }

/*        if (org.springframework.util.StringUtils.isEmpty(channel)) {
            channel = "default";
        }*/

        try {
            UsersPoint usersPoint = userRepository.findUsersPointByOpenIdAndChannel(openid ,channel);
            if(usersPoint==null){

                UsersPoint usersPointTemp = new UsersPoint();
                usersPointTemp.setLastModifyTime(new Date());
                usersPointTemp.setCreateTime(new Date());
                usersPointTemp.setOpenId(openid);
                usersPointTemp.setChannel(channel);
                usersPointTemp.setPointTotal(0);

                userRepository.save(usersPointTemp);


                result.put("status", 0);
                /**
                 * update by lsz 2019年11月20日
                 * 修复用户不存在，空指针异常
                 */
                result.put("message", "没有此用户，但是在用户积分表里加了一条记录！");
                result.put("Total",0);
                result.put("Name", "");
                return result;
            }
            jsonObject.put("Name", usersPoint.getName());
            jsonObject.put("PointTotal", usersPoint.getPointTotal());
            jsonObject.put("status", 0);
            result.put("Name",jsonObject.get("Name"));
            result.put("Total",jsonObject.get("PointTotal"));


            result.put("status", 0);

            /**
             * add by 2019年12月16日 星期一
             */
            result.put("data", usersPoint);

        }catch (Exception e){
            log.error(e.getMessage());
            //事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            result.put("status", 2);
            result.put("message", "查询数据异常");
        }
        log.info(result.toJSONString());
        return result;
    }


    /**
     * add by 2019年12月16日 星期一
     * 消费指定积分
     * @param userNo
     * @param boNo
     * @param pointId
     * @param ts
     * @param appId
     * @param channel
     * @param phoneNumber
     * @param param01
     * @param param02
     * @param sign
     * @return
     */
    @Transactional
    @RequestMapping("/consumeUserPointAssgin")
    public JSONObject consumeUserPointAssgin(@RequestParam(required = true) String userNo, String boNo, @RequestParam(required = true) Integer pointId, String ts, String appId, @RequestParam(defaultValue = "default") String channel, String phoneNumber, String param01, String param02, String sign ,
                                             HttpServletRequest request) {
        JSONObject result = new JSONObject();

        PointFlow pointFlow = pointFlowRepository.findPointFlowByOpenIdAndId(  userNo,pointId);

        try {

            if (pointFlow == null) {

                result.put("status", "2");
                result.put("message", "没有查到这个积分");

            } else if (pointFlow.getStatus() != 0 && "add".equals(pointFlow.getOperation())) { // 此积分为有效状态 ， 可以消费
                pointFlow.setStatus(0);
                pointFlowRepository.saveAndFlush(pointFlow);
//                pointFlow.setOpenId("");
                result.put("status", "0");
                result.put("message", "消费完成");
                result.put("data", pointFlow);

            } else if (pointFlow.getStatus() == 0) {  // 此积分为无效状态，不可消费
//                pointFlow.setOpenId("");

                result.put("status", "1");
                result.put("message", "此积分为无效状态，无法进行消费");
                result.put("data", pointFlow);
            } else if ( !( "add".equals(pointFlow.getOperation())) ) {
                result.put("status", "5");
                result.put("message", "此积分无法进行消费，无法进行消费");
            }


//        消费完成之后将用户积分总数减少
            if ("0".equals(result.getString("status"))) {
                UsersPoint usersPoint = userRepository.findUsersPointByOpenIdAndChannel(userNo, channel);
                if (usersPoint != null) {
                    usersPoint.setPointTotal(usersPoint.getPointTotal() - pointFlow.getCount());
                    usersPoint.setLastModifyTime(new Date());

                    userRepository.saveAndFlush(usersPoint);
                } else {
                    result.put("status", "3");
                    result.put("message", "用户积分流水状态更新完成，但是更新UsersPoint出现异常：查询到UsersPoint为Null。操作回滚");
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

                }
            }
        } catch (TransactionException e) {

        }

//        用户积分总数做减之后，插入一条消费记录流水
        PointFlow pointFlowConsumeTemp = new PointFlow();
        pointFlowConsumeTemp.setOpenId(pointFlow.getOpenId());
        pointFlowConsumeTemp.setStatus(1);
        pointFlowConsumeTemp.setChannel(pointFlow.getChannel());
        pointFlowConsumeTemp.setCount(pointFlow.getCount());
        pointFlowConsumeTemp.setOperation("consume");
        pointFlowConsumeTemp.setOperationTime(new Date());

        PointFlow resultTemp = pointFlowRepository.save(pointFlowConsumeTemp);
        if (resultTemp == null) {
            result.put("status", "4");
            result.put("message", "用户积分流水状态更新完成，更新UsersPoint成功，但是插入消费记录时出异常。");
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

        }


        return result;
    }


/*                    try {



        throw new TransactionUsageException("用户积分流水状态更新完成，但是更新UsersPoint出现异常：查询到UsersPoint为Null。操作回滚");
    } catch (TransactionException e) {
        log.warn(e.getLocalizedMessage());
        //事务回滚
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }*/


    @Autowired
    private UserPointTempRepository userPointTempRepository;



    @Transactional
    @RequestMapping("/convertUnionIdPointToMini")
    public JSONObject consumeUserPointAssgin(@RequestParam(required = true) String unionId, @RequestParam(required = true) String  miniOpenId , String username
                                             , HttpServletRequest request) {
        JSONObject result = new JSONObject();


/*
        userRepository.findUsersPointByOpenIdAndChannel(miniOpenId, "default");

        PointFlow pointFlowTemp = new PointFlow();
        pointFlowTemp.setOpenId(miniOpenId);

        UsersPoint usersPointTemp = new UsersPoint();
        usersPointTemp.setOpenId(miniOpenId);

        long pointRecordCount = pointFlowRepository.count(Example.of(pointFlowTemp));
        pointRecordCount += userRepository.count(Example.of(usersPointTemp));

        if (pointRecordCount > 0) {
            result.put("status", "1");
            result.put("message", "此用户已经在积分平台存在记录：" + miniOpenId);
        }else{*/

            try {
/*                UsersPointTemp usersPointTemp1 = new UsersPointTemp();
                usersPointTemp1.setOpenId(unionId);
                UsersPointTemp temp = userPointTempRepository.findOne(Example.of(usersPointTemp1)).get();

                for (int i = 0; i < temp.getPointTotal(); i++) {
                    String param01 = "" + randomWithNotZero(addPointRandomBound);
                    PointFlow pf = new PointFlow(null, miniOpenId, "add", new Date(), 1, "default", 1, "", param01, null);
                    pointFlowRepository.save(pf);

                }

                UsersPoint usersPoint = new UsersPoint();
                usersPoint.setOpenId(miniOpenId);
                usersPoint.setPointTotal(temp.getPointTotal());
                usersPoint.setChannel("default");
                usersPoint.setCreateTime(new Date());
                usersPoint.setLastModifyTime(new Date());
                usersPoint.setName("" + username);

                userRepository.save(usersPoint);*/

                userRepository.updateUsersPointOpenId(unionId, miniOpenId);
                pointFlowRepository.updatePointFlowOpenId(unionId, miniOpenId);


                result.put("status", "0");
                result.put("message", "转换完成！");

            } catch (Exception e) {
                log.error(e.getMessage());
                result.put("status", "2");
                result.put("message", "转换失败！"+e.getMessage());
            }





        return result;
    }


}
